package mahjong

import (
	"Mahjong-demo/card"
	"container/list"
	"fmt"
)

const (
	// 玩家人数
	playerCount = 4
	// 开局抓牌数
	catchHandCard = 13
)

// Mahjongmahjong 麻将游戏
type Mahjongmahjong struct {
	// 玩家手牌
	// 手牌顺序: 花色筒、条、万，点数从小到大
	handCards []*mahjongList

	// 玩家吃、碰、杠的牌（不能操作）
	playerTableCards []*list.List
	// 桌牌(玩家打出去的牌)
	tableCards *list.List
}

// New 初始化麻将游戏
func New() *Mahjongmahjong {
	handCards := make([]*mahjongList, playerCount, playerCount)
	playerTableCards := make([]*list.List, playerCount, playerCount)
	tableCards := list.New()
	return &Mahjongmahjong{handCards, playerTableCards, tableCards}
}

// Draw 发牌，给玩家们
func (inst *Mahjongmahjong) Draw() {
	mjset := card.GetMahjongSet()
	var cardIDs []int
	for n := 0; n < playerCount; n++ {
		cardIDs = mjset.Draw(catchHandCard)
		inst.handCards[n] = newList(cardIDs)
	}
}

// Chi 吃牌
func (inst *Mahjongmahjong) Chi(playerPos int, cardID int) bool {

	result := inst.handCards[playerPos].chi(cardID)
	if result == nil {
		fmt.Printf("玩家%v, 不能吃%v\n", playerPos, card.GetFriendy(cardID))
		return false
	}

	fmt.Printf("玩家%v, 吃%v\n", playerPos, card.GetFriendy(cardID))
	fmt.Println("可以吃牌的手牌:")
	card.Print(result)

	return true
}

// Ting 听牌
func (inst *Mahjongmahjong) Ting(playerPos int) bool {
	result := inst.handCards[playerPos].ting()
	if result == nil {
		fmt.Printf("玩家%v, 不能听牌", playerPos)
		return false
	}

	fmt.Printf("玩家%v, 听牌: %v\n", playerPos, getCardsName2(result))
	return true
}

// PrintHandCard 打印所有玩家手牌
func (inst *Mahjongmahjong) PrintHandCard() {
	for playerPos, playerHandCard := range inst.handCards {
		idx := 0
		playerHandCard.do(func(cardID int) {
			fmt.Printf("玩家%v, 手牌(%v) %v\n", playerPos, idx, card.GetFriendy(cardID))
			idx++
		})
		fmt.Println()
	}
}

// PrintPlayerHandCard 打印指定玩家手牌
func (inst *Mahjongmahjong) PrintPlayerHandCard(playerPos int) {
	idx := 0
	inst.handCards[playerPos].do(func(cardID int) {
		fmt.Printf("玩家%v, 手牌(%v) %v\n", playerPos, idx, card.GetFriendy(cardID))
		idx++
	})
	fmt.Println()
}

// // TestDataChi 制造吃牌测试数据
// func (inst *Mahjongmahjong) TestDataChi() {
// 	// 吃牌测试:修改玩家3的手牌
// 	inst.handCards[3] = newList([]int{1, 2, 4, 5, 11, 20, 21, 21, 23, 24, 24, 25, 26})
// }

// // TestPengGang 测试碰和杠牌
// func (inst *Mahjongmahjong) TestPengGang() {
// 	// 碰, 杠 牌测试:修改玩家3的手牌
// 	inst.handCards[3] = newList([]int{1, 1, 1, 5, 11, 20, 21, 21, 23, 24, 24, 25, 26})

// 	fmt.Printf("peng test1: %v\n", inst.handCards[3].peng(24) == true)
// 	fmt.Printf("peng test2: %v\n", inst.handCards[3].peng(5) == false)
// 	fmt.Printf("peng test3: %v\n", inst.handCards[3].peng(1) == true)

// 	fmt.Printf("gang test1: %v\n", inst.handCards[3].gang(24) == false)
// 	fmt.Printf("gang test2: %v\n", inst.handCards[3].gang(1) == true)
// 	fmt.Printf("gang test3: %v\n", inst.handCards[3].gang(11) == false)
// }

// // TestListOpt 测试麻将列表操作
// func (inst *Mahjongmahjong) TestListOpt() {
// 	inst.PrintPlayerHandCard(3)
// 	inst.handCards[3].drop(11)
// 	inst.handCards[3].add(10)
// 	inst.handCards[3].swap(10, 12)
// }

type testInfo struct {
	handCard []int
	expect   bool
}

// TestTing 测试听牌
func TestTing() bool {
	mj := New()
	mj.Draw()

	testData := map[string]testInfo{
		"九莲宝灯": testInfo{
			[]int{0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8},
			true,
		},
		"七对": {
			[]int{0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6},
			true,
		},
		"没有缺门": {
			[]int{1, 2, 1, 5, 11, 20, 21, 21, 23, 24, 24, 25, 26},
			false,
		},
		"没有将牌": {
			[]int{1, 2, 3, 6, 7, 19, 20, 21, 22, 23, 24, 25, 26},
			false,
		},
		"顺子拆牌测试": {
			[]int{1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6},
			true,
		},
	}

	var playerPos = 3
	resultTips := map[bool]string{
		true:  "测试成功~",
		false: "测试失败!!!",
	}

	var okCount = 0
	for name, data := range testData {
		// fmt.Println("开始测试 ==【"+name+"】")
		mj.handCards[playerPos] = newList(data.handCard)
		// mj.PrintPlayerHandCard(playerPos)
		ok := mj.Ting(playerPos) == data.expect
		if ok {
			okCount++
		}
		fmt.Println("【"+name+"】", resultTips[ok])
	}

	return okCount == len(testData)
}
